route.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import { NextRequest, NextResponse } from 'next/server';
  2. import { getServerSession } from 'next-auth';
  3. import { authOptions } from '@/lib/auth';
  4. import { db } from '@/lib/db';
  5. import { sections, classes, periods, studentEnrollments, eq, and, ne } from '@/lib/db/schema';
  6. interface RouteContext {
  7. params: Promise<{ id: string }>;
  8. }
  9. export async function PUT(request: NextRequest, context: RouteContext) {
  10. try {
  11. const session = await getServerSession(authOptions);
  12. if (!session?.user || session.user.role !== 'admin') {
  13. return NextResponse.json(
  14. { error: 'No autorizado' },
  15. { status: 401 }
  16. );
  17. }
  18. const { id } = await context.params;
  19. const { name, classId, periodId, maxStudents } = await request.json();
  20. // Validaciones
  21. if (!name || !classId || !periodId || !maxStudents) {
  22. return NextResponse.json(
  23. { error: 'Todos los campos son requeridos' },
  24. { status: 400 }
  25. );
  26. }
  27. if (typeof maxStudents !== 'number' || maxStudents < 1) {
  28. return NextResponse.json(
  29. { error: 'El número máximo de estudiantes debe ser mayor a 0' },
  30. { status: 400 }
  31. );
  32. }
  33. // Verificar si la sección existe
  34. const existingSection = await db
  35. .select()
  36. .from(sections)
  37. .where(eq(sections.id, id))
  38. .limit(1);
  39. if (existingSection.length === 0) {
  40. return NextResponse.json(
  41. { error: 'Sección no encontrada' },
  42. { status: 404 }
  43. );
  44. }
  45. // Verificar si la clase existe
  46. const existingClass = await db
  47. .select()
  48. .from(classes)
  49. .where(eq(classes.id, classId))
  50. .limit(1);
  51. if (existingClass.length === 0) {
  52. return NextResponse.json(
  53. { error: 'La clase seleccionada no existe' },
  54. { status: 400 }
  55. );
  56. }
  57. // Verificar si el período existe
  58. const existingPeriod = await db
  59. .select()
  60. .from(periods)
  61. .where(eq(periods.id, periodId))
  62. .limit(1);
  63. if (existingPeriod.length === 0) {
  64. return NextResponse.json(
  65. { error: 'El período seleccionado no existe' },
  66. { status: 400 }
  67. );
  68. }
  69. // Verificar si ya existe otra sección con el mismo nombre para la misma clase y período
  70. const duplicateSection = await db
  71. .select()
  72. .from(sections)
  73. .where(and(
  74. eq(sections.name, name),
  75. eq(sections.classId, classId),
  76. eq(sections.periodId, periodId),
  77. ne(sections.id, id)
  78. ))
  79. .limit(1);
  80. if (duplicateSection.length > 0) {
  81. return NextResponse.json(
  82. { error: 'Ya existe otra sección con este nombre para la misma clase y período' },
  83. { status: 400 }
  84. );
  85. }
  86. // Verificar si el nuevo límite de estudiantes es menor al número actual de estudiantes inscritos
  87. const currentEnrollments = await db
  88. .select()
  89. .from(studentEnrollments)
  90. .where(eq(studentEnrollments.sectionId, id));
  91. if (maxStudents < currentEnrollments.length) {
  92. return NextResponse.json(
  93. { error: `No se puede reducir el límite a ${maxStudents} porque hay ${currentEnrollments.length} estudiantes inscritos` },
  94. { status: 400 }
  95. );
  96. }
  97. // Actualizar sección
  98. const updatedSection = await db
  99. .update(sections)
  100. .set({
  101. name,
  102. classId,
  103. periodId,
  104. maxStudents,
  105. updatedAt: new Date(),
  106. })
  107. .where(eq(sections.id, id))
  108. .returning({
  109. id: sections.id,
  110. name: sections.name,
  111. classId: sections.classId,
  112. periodId: sections.periodId,
  113. maxStudents: sections.maxStudents,
  114. isActive: sections.isActive,
  115. updatedAt: sections.updatedAt,
  116. });
  117. return NextResponse.json(updatedSection[0]);
  118. } catch (error) {
  119. console.error('Error updating section:', error);
  120. return NextResponse.json(
  121. { error: 'Error interno del servidor' },
  122. { status: 500 }
  123. );
  124. }
  125. }
  126. export async function DELETE(request: NextRequest, context: RouteContext) {
  127. try {
  128. const session = await getServerSession(authOptions);
  129. if (!session?.user || session.user.role !== 'admin') {
  130. return NextResponse.json(
  131. { error: 'No autorizado' },
  132. { status: 401 }
  133. );
  134. }
  135. const { id } = await context.params;
  136. // Verificar si la sección existe
  137. const existingSection = await db
  138. .select()
  139. .from(sections)
  140. .where(eq(sections.id, id))
  141. .limit(1);
  142. if (existingSection.length === 0) {
  143. return NextResponse.json(
  144. { error: 'Sección no encontrada' },
  145. { status: 404 }
  146. );
  147. }
  148. // Verificar si la sección tiene estudiantes inscritos
  149. const enrolledStudents = await db
  150. .select()
  151. .from(studentEnrollments)
  152. .where(eq(studentEnrollments.sectionId, id))
  153. .limit(1);
  154. if (enrolledStudents.length > 0) {
  155. return NextResponse.json(
  156. { error: 'No se puede eliminar la sección porque tiene estudiantes inscritos' },
  157. { status: 400 }
  158. );
  159. }
  160. // Eliminar sección (soft delete)
  161. await db
  162. .update(sections)
  163. .set({
  164. isActive: false,
  165. updatedAt: new Date(),
  166. })
  167. .where(eq(sections.id, id));
  168. return NextResponse.json(
  169. { message: 'Sección eliminada exitosamente' },
  170. { status: 200 }
  171. );
  172. } catch (error) {
  173. console.error('Error deleting section:', error);
  174. return NextResponse.json(
  175. { error: 'Error interno del servidor' },
  176. { status: 500 }
  177. );
  178. }
  179. }